/******************************************************************************
	This file is a part of the Snapshot Bioinformatics Project

	Copyright (C) 2012-2013 Jarom Schow

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/

#include "ConnectWiz.h"

#include <QtWidgets/QCheckBox>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QFileDialog>
#include <QtWidgets/QGridLayout>
#include <QtWidgets/QGroupBox>
#include <QtWidgets/QLabel>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QMessageBox>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QRadioButton>

#include "ConnectFrame.h"
#include "Progress.h"
#include "StaticTextBrowser.h"
#include "FileUtil.h"

const double	c_kilobyte = 1024.0;
const double	c_megabyte = c_kilobyte * c_kilobyte;
const double	c_gigabyte = c_kilobyte * c_megabyte;

const int		c_postgreDefaultPort = 5432;
const int		c_mySqlDefaultPort = 3306;

const QString	c_createDB( "CreateDB" );
const QString	c_embedded( "Embedded" );
const QString	c_serverType( "ServerType" );
const QString	c_hostName( "HostName" );
const QString	c_portNumber( "PortNumber" );
const QString	c_userName( "UserName" );
const QString	c_password( "Password" );
const QString	c_dbName( "DBName" );
const QString	c_configPath( "ConfigPath" );
const QString	c_newConfigPath( "NewConfigPath" );
const QString	c_genBankPrefix( "GenBank_" );
const QString	c_createBioUser( "CreateBioUser" );
const QString	c_createReadOnly( "CreateReadOnly" );
const QString	c_bioUserName( "BioUserName" );
const QString	c_bioUserPass( "BioUserPassword" );
const QString	c_readOnlyName( "ReadOnlyName" );
const QString	c_readOnlyPass( "ReadOnlyPassword" );

const QString	c_defaultHost( "127.0.0.1" );

///////////////////////////////////////////////////////////////////////////////
//	SnapshotWiz
///////////////////////////////////////////////////////////////////////////////

/**
**/
SnapshotWiz::SnapshotWiz( QWidget *parent ) : QWizard( parent )
{
}

/**
**/
SnapshotWiz::~SnapshotWiz()
{
}

/**
**/
bool SnapshotWiz::isDivisionSelected( Bio::GenBank::Division div ) const
{
	return field( c_genBankPrefix + Bio::GenBank::getDivisionAbbreviation( div ) ).toBool();
}

///////////////////////////////////////////////////////////////////////////////
//	GenBankWiz
///////////////////////////////////////////////////////////////////////////////

/**
**/
GenBankWiz::GenBankWiz( QWidget *parent, Bio::GenBank *genBank ) : SnapshotWiz( parent )
{
	setWindowTitle( tr( "GenBank data loading wizard" ) );

	setPage( PageGenBank, new GenBankPage( genBank ) );
	setPage( PageFinish, new FinishedPage( false ) );
}

/**
**/
GenBankWiz::~GenBankWiz()
{
}

///////////////////////////////////////////////////////////////////////////////
//	ConnectWiz
///////////////////////////////////////////////////////////////////////////////

/**
**/
ConnectWiz::ConnectWiz( QWidget *parent, Bio::GenBank *genBank, const QString &defConfigFile ) : SnapshotWiz( parent )
{
	setWindowTitle( tr( "BioSQL Database connection wizard" ) );

	setPage( PageIntro, new IntroPage );
	setPage( PageCreate, new CreatePage );
	setPage( PageConnect, new ConnectPage( defConfigFile ) );
	setPage( PageEmbedded, new EmbeddedPage( defConfigFile ) );
	setPage( PageMySQL, new MySQLPage );
	setPage( PagePostgre, new PostgrePage );
	setPage( PageUsers, new UsersPage );
	setPage( PageGenBank, new GenBankPage( genBank ) );
	setPage( PageFinish, new FinishedPage( true ) );
}

/**
**/
ConnectWiz::~ConnectWiz()
{
}

/**
**/
Bio::SqlServerSettings ConnectWiz::getServerSettings() const
{
	Bio::SqlServerSettings	settings;

	if( field( c_embedded ).toBool() ){
		settings.setServerType( Bio::SqlServerSettings::MySQLEmbedded );
		settings.setConfigurationFile( field( c_newConfigPath ).toString() + "/my.ini" );
	}
	else {
		int	idx = field( c_serverType ).toInt();

		if( idx == 0 ){
			settings.setServerType( Bio::SqlServerSettings::MySQLEmbedded );
			settings.setConfigurationFile( field( c_configPath ).toString() + "/my.ini" );
		}
		else {
			if( idx == 1 )
				settings.setServerType( Bio::SqlServerSettings::MySQL );
			else if( idx == 2 )
				settings.setServerType( Bio::SqlServerSettings::PostgreSQL );

			settings.setHostName( field( c_hostName ).toString() );
			settings.setPort( field( c_portNumber ).toInt() );
			settings.setUserName( field( c_userName ).toString() );
			settings.setPassword( field( c_password ).toString() );
			settings.setDatabaseName( field( c_dbName ).toString() );
		}
	}

	return settings;
}

/**
**/
bool ConnectWiz::isCreate() const
{
	return field( c_createDB ).toBool();
}

///////////////////////////////////////////////////////////////////////////////
//	IntroPage
///////////////////////////////////////////////////////////////////////////////

/**
**/
IntroPage::IntroPage()
{
	QVBoxLayout		*layout = new QVBoxLayout;
	QLabel			*label;

	setLayout( layout );
	setTitle( "Introduction" );

	label = new QLabel( "This wizard will help you setup a BioSQL database for Snapshot." );
	label->setWordWrap( true );
	layout->addWidget( label );
	
	m_createBtn = new QRadioButton( "Create a new BioSQL database" );
	m_createBtn->setChecked( true );
	m_createBtn->setToolTip( "Select this option to be guided through creating a new BioSQL database." );
	m_createBtn->setWhatsThis( "Selecting this option will walk you through the steps of setting up a new "
		"BioSQL database." );
	layout->addWidget( m_createBtn );

	m_connectBtn = new QRadioButton( "Connect to an existing BioSQL database" );
	m_connectBtn->setToolTip( "Select this option to connect to an existing database." );
	m_connectBtn->setWhatsThis( "Selecting this option will take you to a page where you can enter the "
		"connection details to connect Snapshot to an existing database." );
	layout->addWidget( m_connectBtn );

	registerField( c_createDB, m_createBtn );
}

/**
**/
IntroPage::~IntroPage()
{
}

/**
**/
int IntroPage::nextId() const
{
	if( m_connectBtn->isChecked() )
		return SnapshotWiz::PageConnect;
	
	return SnapshotWiz::PageCreate;
}

///////////////////////////////////////////////////////////////////////////////
//	ConnectPage
///////////////////////////////////////////////////////////////////////////////

/**
**/
ConnectPage::ConnectPage( const QString &defConfigFile ) : m_complete( false )
{
	QVBoxLayout	*layout = new QVBoxLayout;

	setTitle( "Connect to Database" );
	setLayout( layout );

	Bio::SqlServerSettings	settings;

	settings.setServerType( Bio::SqlServerSettings::MySQL );
	settings.setHostName( c_defaultHost );
	settings.setConfigurationFile( Bio::FileUtil::getPath( defConfigFile ) );

	m_frame = new ConnectFrame( this, settings );
	layout->addWidget( m_frame );

	registerField( c_serverType, m_frame->m_serverTypeCombo );
	registerField( c_hostName, m_frame->m_hostEdit );
	registerField( c_portNumber, m_frame->m_portEdit );
	registerField( c_userName, m_frame->m_userEdit );
	registerField( c_password, m_frame->m_passEdit );
	registerField( c_dbName, m_frame->m_dbNameEdit );
	registerField( c_configPath, m_frame->m_locationEdit );

	connect( m_frame->m_hostEdit, SIGNAL(textEdited(const QString&)), this, SLOT(updateComplete()) );
	connect( m_frame->m_portEdit, SIGNAL(textEdited(const QString&)), this, SLOT(updateComplete()) );
	connect( m_frame->m_userEdit, SIGNAL(textEdited(const QString&)), this, SLOT(updateComplete()) );
	connect( m_frame->m_dbNameEdit, SIGNAL(textEdited(const QString&)), this, SLOT(updateComplete()) );
	connect( m_frame->m_locationEdit, SIGNAL(textEdited(const QString&)), this, SLOT(updateComplete()) );
}

/**
**/
ConnectPage::~ConnectPage()
{
}

/**
**/
int ConnectPage::nextId() const
{
	if( field( c_createDB ).toBool() )
		return SnapshotWiz::PageUsers;

	return SnapshotWiz::PageFinish;
}

/**
**/
bool ConnectPage::isComplete() const
{
	if( m_frame->m_serverTypeCombo->currentIndex() == 0 ){
		if( m_frame->m_locationEdit->text().isEmpty() )
			return false;
	}
	else {
		if( m_frame->m_hostEdit->text().isEmpty() )
			return false;

		if( m_frame->m_portEdit->text().isEmpty() )
			return false;

		if( m_frame->m_userEdit->text().isEmpty() )
			return false;

		if( m_frame->m_dbNameEdit->text().isEmpty() )
			return false;
	}

	return true;
}

/**
**/
void ConnectPage::initializePage()
{
	m_complete = isComplete();
}

/**
**/
void ConnectPage::updateComplete()
{
	if( m_complete == isComplete() )
		return;

	m_complete = isComplete();
	emit completeChanged();
}

///////////////////////////////////////////////////////////////////////////////
//	EmbeddedPage
///////////////////////////////////////////////////////////////////////////////

/**
**/
EmbeddedPage::EmbeddedPage( const QString &defConfigFile ) : m_complete( false )
{
	QVBoxLayout	*layout = new QVBoxLayout;
	QLabel		*label;
	QPushButton	*btn;

	setTitle( "Setup MySQL Embedded" );
	setLayout( layout );

	label = new QLabel( "Select a location for the MySQL data files. These files can become very large, "
					"so you will want to select a location on a drive with plenty of free space." );
	label->setWordWrap( true );
	layout->addWidget( label );

	QHBoxLayout	*hbox = new QHBoxLayout;

	label = new QLabel( tr( "Database Location:" ), this );
	hbox->addWidget( label );

	m_configPath = new QLineEdit( this );
	m_configPath->setText( Bio::FileUtil::getPath( defConfigFile ) );
	hbox->addWidget( m_configPath, 100 );

	btn = new QPushButton( "...", this );
	btn->setFixedWidth( 30 );
	connect( btn, SIGNAL(clicked()), this, SLOT(browseLocation()) );
	hbox->addWidget( btn );

	layout->addLayout( hbox );

	registerField( c_newConfigPath, m_configPath );

	connect( m_configPath, SIGNAL(textEdited(const QString&)), this, SLOT(updateComplete()) );
}

/**
**/
EmbeddedPage::~EmbeddedPage()
{
}

/**
**/
int EmbeddedPage::nextId() const
{
	return SnapshotWiz::PageGenBank;
}

/**
**/
bool EmbeddedPage::isComplete() const
{
	if( m_configPath->text().isEmpty() )
		return false;

	return true;
}

/**
**/
void EmbeddedPage::initializePage()
{
	m_complete = isComplete();
}

/**
**/
void EmbeddedPage::updateComplete()
{
	if( m_complete == isComplete() )
		return;

	m_complete = isComplete();
	emit completeChanged();
}

/**
**/
void EmbeddedPage::browseLocation()
{
	QString	newDir = QFileDialog::getExistingDirectory( this, tr( "Select a directory for the database files" ), 
						m_configPath->text() );

	if( !newDir.isEmpty() )
		m_configPath->setText( newDir );
}

///////////////////////////////////////////////////////////////////////////////
//	CreatePage
///////////////////////////////////////////////////////////////////////////////

/**
**/
CreatePage::CreatePage()
{
	QVBoxLayout		*layout = new QVBoxLayout;
	QLabel			*label;

	setLayout( layout );
	setTitle( "Create a New BioSQL Database" );

	label = new QLabel( "In order to create a new BioSQL database, you must have a database server. "
		"The easiest option is to use the embedded MySQL database which requires no extra download, "
		"but can not be shared with other computers. The other options require you to download and "
		"install a database server, or connect to an existing database server on another computer. "
		"Using a standalone database server allows you to share the BioSQL database across a local "
		"network." );
	label->setWordWrap( true );
	layout->addWidget( label );

	m_embedBtn = new QRadioButton( "Use the embedded MySQL database" );
	m_embedBtn->setToolTip( "Select this option to use the MySQL database that comes with Snapshot." );
	m_embedBtn->setWhatsThis( "Selecting this option will setup a BioSQL database using the MySQL "
		"database that comes with Snapshot. This database can only be accessed on the local computer." );
	layout->addWidget( m_embedBtn );

	m_mysqlBtn = new QRadioButton( "Install a MySQL server" );
	m_mysqlBtn->setToolTip( "Select this option to see a MySQL tutorial." );
	m_mysqlBtn->setWhatsThis( "Selecting this option will show you a tutorial on setting up a "
		"new MySQL server which can be used to host a BioSQL database." );
	layout->addWidget( m_mysqlBtn );

	m_postgreBtn = new QRadioButton( "Install a PostgreSQL server" );
	m_postgreBtn->setToolTip( "Select this option to see a PostgreSQL tutorial." );
	m_postgreBtn->setWhatsThis( "Selecting this option will show you a tutorial on setting up a "
		"new PostgreSQL server which can be used to host a BioSQL database." );
	layout->addWidget( m_postgreBtn );

	m_connectBtn = new QRadioButton( "Use an existing database server" );
	m_connectBtn->setToolTip( "Select this option to create a new BioSQL database on an existing server." );
	m_connectBtn->setWhatsThis( "Selecting this option will allow you to connect to an existing PostgreSQL or "
		"MySQL server to create a new BioSQL database." );
	layout->addWidget( m_connectBtn );

	registerField( c_embedded, m_embedBtn );
}

/**
**/
CreatePage::~CreatePage()
{
}

/**
**/
int CreatePage::nextId() const
{
	if( m_embedBtn->isChecked() )
		return SnapshotWiz::PageEmbedded;

	if( m_mysqlBtn->isChecked() )
		return SnapshotWiz::PageMySQL;
	
	if( m_postgreBtn->isChecked() )
		return SnapshotWiz::PagePostgre;
	
	return SnapshotWiz::PageConnect;
}

/**
**/
void CreatePage::initializePage()
{
	m_embedBtn->setChecked( true );
}

///////////////////////////////////////////////////////////////////////////////
//	PostgrePage
///////////////////////////////////////////////////////////////////////////////

/**
**/
PostgrePage::PostgrePage()
{
	QVBoxLayout		*layout = new QVBoxLayout;

	setLayout( layout );
	setTitle( "PostgreSQL Tutorial" );

	QString	str =	"<HTML><BODY>"
					"<OL>"
					"<LI>Download the PostgreSQL installer from <A HREF=\"http://www.postgresql.org/download/\">www.postgresql.org</A></LI>"
					"<LI>Run the installer</LI>"
					"<LI>When prompted, enter a password for the superuser. You will need this to create the BioSQL database.</LI>"
					"<LI>Select the port for the database. Leave the default (5432) unless you need to change it.</LI>"
					"<LI>Wait for the installer to finish.</LI>"
					"</OL>"
					"</BODY></HTML>";
					

	StaticTextBrowser	*browser = new StaticTextBrowser( str, this );

	layout->addWidget( browser );
}

/**
**/
PostgrePage::~PostgrePage()
{
}

/**
**/
bool PostgrePage::validatePage()
{
	setField( c_serverType, QVariant( 0 ) );
	setField( c_hostName, QVariant( "127.0.0.1" ) );
	setField( c_portNumber, QVariant( c_postgreDefaultPort ) );
	setField( c_userName, QVariant( "postgres" ) );
	setField( c_dbName, QVariant( "biosql" ) );

	return true;
}

/**
**/
int PostgrePage::nextId() const
{
	return SnapshotWiz::PageConnect;
}

///////////////////////////////////////////////////////////////////////////////
//	MySQLPage
///////////////////////////////////////////////////////////////////////////////

/**
**/
MySQLPage::MySQLPage()
{
	QVBoxLayout		*layout = new QVBoxLayout;

	setLayout( layout );
	setTitle( "MySQL Tutorial" );

	QString	str =	"<HTML><BODY>"
					"<OL>"
					"<LI>Download the MySQL installer from <A HREF=\"http://www.mysql.com/downloads/\">www.mysql.com</A></LI>"
					"<LI>Run the installer</LI>"
					"<LI>Choose the setup type. 'Server only' or 'Full' are recommended.</LI>"
					"<LI>Configure the server:</LI>"
					"<UL>"
					"<LI>Choose the Server configuration type that is appropriate for you.</LI>"
					"<LI>Enable TCP/IP Networking and select the port (3306 is typical)</LI>"
					"<LI>Enter a password for the root user. You will need this to create the BioSQL database.</LI>"
					"</UL>"
					"<LI>Wait for the installer to finish.</LI>"
					"</OL>"
					"</BODY></HTML>";

	StaticTextBrowser	*browser = new StaticTextBrowser( str, this );

	layout->addWidget( browser );
}

/**
**/
MySQLPage::~MySQLPage()
{
}

/**
**/
bool MySQLPage::validatePage()
{
	setField( c_serverType, QVariant( 1 ) );
	setField( c_hostName, QVariant( "127.0.0.1" ) );
	setField( c_portNumber, QVariant( c_mySqlDefaultPort ) );
	setField( c_userName, QVariant( "root" ) );
	setField( c_dbName, QVariant( "biosql" ) );

	return true;
}

/**
**/
int MySQLPage::nextId() const
{
	return SnapshotWiz::PageConnect;
}

///////////////////////////////////////////////////////////////////////////////
//	UsersPage
///////////////////////////////////////////////////////////////////////////////

/**
**/
UsersPage::UsersPage() : m_complete( false )
{
	setTitle( "Create Database Users" );

	buildUI();
}

/**
**/
UsersPage::~UsersPage()
{
}

/**
**/
int UsersPage::nextId() const
{
	return SnapshotWiz::PageGenBank;
}

/**
**/
bool UsersPage::isComplete() const
{
	if( m_bioUserBox->isChecked() ){
		if( m_bioUserName->text().isEmpty() )
			return false;

		if( m_bioPass1->text() != m_bioPass2->text() )
			return false;
	}

	if( m_readOnlyBox->isChecked() ){
		if( m_readOnlyName->text().isEmpty() )
			return false;

		if( m_readOnlyPass1->text() != m_readOnlyPass2->text() )
			return false;
	}

	return true;
}

/**
**/
void UsersPage::initializePage()
{
	m_complete = isComplete();
}

/**
**/
void UsersPage::updateComplete()
{
	if( m_complete == isComplete() )
		return;

	m_complete = isComplete();
	emit completeChanged();
}

/**
**/
void UsersPage::buildUI()
{
	QVBoxLayout		*layout = new QVBoxLayout;
	QGridLayout		*boxLayout;
	QLabel			*label;

	setLayout( layout );

	label = new QLabel( "It is recommended that you create a new database user account for working with the BioSQL database. "
		"You can also create a read-only account to give to users who only need read access to the database." );
	label->setWordWrap( true );
	layout->addWidget( label );
	
	m_bioUserBox = new QGroupBox( "Create BioSQL user", this );
	m_bioUserBox->setCheckable( true );
	m_bioUserBox->setChecked( true );
	layout->addWidget( m_bioUserBox );

	boxLayout = new QGridLayout;
	m_bioUserBox->setLayout( boxLayout );

	label = new QLabel( "User name:", m_bioUserBox );
	boxLayout->addWidget( label, 0, 0 );

	m_bioUserName = new QLineEdit( "bio", m_bioUserBox );
	boxLayout->addWidget( m_bioUserName, 0, 1 );

	label = new QLabel( "Password:", m_bioUserBox );
	boxLayout->addWidget( label, 1, 0 );

	m_bioPass1 = new QLineEdit( m_bioUserBox );
	m_bioPass1->setEchoMode( QLineEdit::Password );
	boxLayout->addWidget( m_bioPass1, 1, 1 );

	label = new QLabel( "Password (again):", m_bioUserBox );
	boxLayout->addWidget( label, 2, 0 );

	m_bioPass2 = new QLineEdit( m_bioUserBox );
	m_bioPass2->setEchoMode( QLineEdit::Password );
	boxLayout->addWidget( m_bioPass2, 2, 1 );
	
	m_readOnlyBox = new QGroupBox( "Create Read-only user", this );
	m_readOnlyBox->setCheckable( true );
	m_readOnlyBox->setChecked( false );
	layout->addWidget( m_readOnlyBox );

	boxLayout = new QGridLayout;
	m_readOnlyBox->setLayout( boxLayout );

	label = new QLabel( "User name:", m_readOnlyBox );
	boxLayout->addWidget( label, 0, 0 );

	m_readOnlyName = new QLineEdit( m_readOnlyBox );
	boxLayout->addWidget( m_readOnlyName, 0, 1 );

	label = new QLabel( "Password:", m_readOnlyBox );
	boxLayout->addWidget( label, 1, 0 );

	m_readOnlyPass1 = new QLineEdit( m_readOnlyBox );
	m_readOnlyPass1->setEchoMode( QLineEdit::Password );
	boxLayout->addWidget( m_readOnlyPass1, 1, 1 );

	label = new QLabel( "Password (again):", m_readOnlyBox );
	boxLayout->addWidget( label, 2, 0 );

	m_readOnlyPass2 = new QLineEdit( m_readOnlyBox );
	m_readOnlyPass2->setEchoMode( QLineEdit::Password );
	boxLayout->addWidget( m_readOnlyPass2, 2, 1 );

	registerField( c_createBioUser, m_bioUserBox );
	registerField( c_bioUserName, m_bioUserName );
	registerField( c_bioUserPass, m_bioPass1 );

	registerField( c_createReadOnly, m_readOnlyBox );
	registerField( c_readOnlyName, m_readOnlyName );
	registerField( c_readOnlyPass, m_readOnlyPass1 );

	connect( m_bioUserBox, SIGNAL(toggled(bool)), this, SLOT(updateComplete()) );
	connect( m_readOnlyBox, SIGNAL(toggled(bool)), this, SLOT(updateComplete()) );

	connect( m_bioUserName, SIGNAL(textEdited(const QString&)), this, SLOT(updateComplete()) );
	connect( m_bioPass1, SIGNAL(textEdited(const QString&)), this, SLOT(updateComplete()) );
	connect( m_bioPass2, SIGNAL(textEdited(const QString&)), this, SLOT(updateComplete()) );
	connect( m_readOnlyName, SIGNAL(textEdited(const QString&)), this, SLOT(updateComplete()) );
	connect( m_readOnlyPass1, SIGNAL(textEdited(const QString&)), this, SLOT(updateComplete()) );
	connect( m_readOnlyPass2, SIGNAL(textEdited(const QString&)), this, SLOT(updateComplete()) );

	setOnlineHelp();
}

/**
**/
void UsersPage::setOnlineHelp()
{
	m_bioUserBox->setToolTip( "Create a user that has full access to the BioSQL database." );
	m_bioUserBox->setWhatsThis( "Selecting this box allows you to create a new database user that will have "
		"full access privileges to the new BioSQL database. This user will be able add, change, or remove data "
		"in the database as well as read data from the database. This user will only be given access to the BioSQL "
		"database and will have no other privileges on the database server." );

	m_bioUserName->setToolTip( "Enter the name of the new user." );
	m_bioUserName->setWhatsThis( "This will be the new user name that will be used to log onto the BioSQL database." );

	m_bioPass1->setToolTip( "Enter a password for the new user." );
	m_bioPass1->setWhatsThis( "Enter the password for the new user." );

	m_bioPass2->setToolTip( "Re-enter the password for the new user." );
	m_bioPass2->setWhatsThis( "Re-enter the password for the new user." );

	m_readOnlyBox->setToolTip( "Create a user that has read-only access to the BioSQL database." );
	m_readOnlyBox->setWhatsThis( "Selecting this box allows you to create a new database user that will have "
		"read-only privileges for the new BioSQL database. This user will be able to use Snapshot to read data "
		"from the database but will not be able to change data. This user will only be given access to the BioSQL "
		"database and will have no other privileges on the database server." );

	m_readOnlyName->setToolTip( "Enter the name of the new user." );
	m_readOnlyName->setWhatsThis( "This will be the new user name that will be used to log onto the BioSQL database." );

	m_readOnlyPass1->setToolTip( "Enter a password for the new user." );
	m_readOnlyPass1->setWhatsThis( "Enter a password for the new user." );

	m_readOnlyPass2->setToolTip( "Re-enter the password for the new user." );
	m_readOnlyPass2->setWhatsThis( "Re-enter the password for the new user." );
}

///////////////////////////////////////////////////////////////////////////////
//	GenBankPage
///////////////////////////////////////////////////////////////////////////////

/**
**/
GenBankPage::GenBankPage( Bio::GenBank *genBank ) : m_genBank( genBank )
{
	setTitle( "Select GenBank Divisions to download" );

	initLayout();
}

/**
**/
GenBankPage::~GenBankPage()
{
	m_genBank = NULL;
}

/**
**/
int GenBankPage::nextId() const
{
	return SnapshotWiz::PageFinish;
}

/**
**/
void GenBankPage::initializePage()
{
	Bio::Progress	progress( "Connecting to GenBank...", -1 );

	if( !m_genBank->connectToGenBank() ){
		QMessageBox::critical( this, "Load sequences from GenBank", "Failed to connect to the GenBank ftp. "
			"Check the log file for details." );
		return;
	}

	progress.finish();

	for( int i = 0; i < Bio::GenBank::NumDivisions; i++ ){
		QString	text = m_divBox[i]->text();

		text += " (" + sizeToText( double( m_genBank->getDivisionSize( Bio::GenBank::Division( i ) ) ) ) + ")";
		m_divBox[i]->setText( text );
	}
}

/**
**/
void GenBankPage::initLayout()
{
	QGridLayout	*layout = new QGridLayout;
	int			row = 0;
	int			colSize = (Bio::GenBank::NumDivisions / 2) + (Bio::GenBank::NumDivisions % 2);

	setLayout( layout );

	for( int i = 0; i < colSize; i++ )
		layout->addWidget( createDivisionCheckBox( i ), row++, 0 );

	row = 0;

	for( int i = colSize; i < Bio::GenBank::NumDivisions; i++ )
		layout->addWidget( createDivisionCheckBox( i ), row++, 1 );

	row = colSize;

	layout->setRowMinimumHeight( row++, 20 );

	m_totalSizeLbl = new QLabel( this );
	layout->addWidget( m_totalSizeLbl, row, 0 );

	updateTotal();
}

/**
**/
void GenBankPage::updateTotal()
{
	double	size = 0.0;

	for( int i = 0; i < Bio::GenBank::NumDivisions; i++ ){
		if( m_divBox[i]->isChecked() ){
			size += double( m_genBank->getDivisionSize( Bio::GenBank::Division( i ) ) );
		}
	}

	m_totalSizeLbl->setText( "Total Download Size: " + sizeToText( size ) );
}

/**
**/
QCheckBox* GenBankPage::createDivisionCheckBox( int which )
{
	Bio::GenBank::Division	div = Bio::GenBank::Division( which );
	QString					abbr = Bio::GenBank::getDivisionAbbreviation( div );
	QString					desc = Bio::GenBank::getDivisionDescription( div );
	QString					text = abbr + " - " + desc;

	m_divBox[which] = new QCheckBox( text, this );
	m_divBox[which]->setToolTip( QString( "Check to get the %1 division from GenBank" ).arg( abbr ) );
	m_divBox[which]->setWhatsThis( QString( "Selecting this option will download all of the flat files for the %1 "
		"division of GenBank and load them into the new BioSQL database." ).arg( abbr ) ); 
	connect( m_divBox[which], SIGNAL(stateChanged(int)), this, SLOT(updateTotal()) );
	
	registerField( c_genBankPrefix + Bio::GenBank::getDivisionAbbreviation( div ), m_divBox[which] );

	return m_divBox[which];
}

/**
**/
QString GenBankPage::sizeToText( double size )
{
	if( size > c_gigabyte )
		return QString( "%1 GB" ).arg( size / c_gigabyte, 0, 'f', 1 );

	if( size > c_megabyte )
		return QString( "%1 MB" ).arg( size / c_megabyte, 0, 'f', 1 );

	if( size > c_kilobyte )
		return QString( "%1 KB" ).arg( size / c_kilobyte, 0, 'f', 1 );

	return QString( "%1 Bytes" ).arg( int( size ) );
}

///////////////////////////////////////////////////////////////////////////////
//	FinishedPage
///////////////////////////////////////////////////////////////////////////////

/**
**/
FinishedPage::FinishedPage( bool checkConnection ) : m_checkConnection( checkConnection )
{
	QVBoxLayout		*layout = new QVBoxLayout;

	setLayout( layout );

	m_lbl = new QLabel( this );
	m_lbl->setWordWrap( true );
	layout->addWidget( m_lbl );
}

/**
**/
FinishedPage::~FinishedPage()
{
}

/**
**/
int FinishedPage::nextId() const
{
	return -1;
}

/**
**/
void FinishedPage::initializePage()
{
	if( !m_checkConnection ){
		setTitle( "Finished" );
		m_lbl->setText( "Click 'Finish' to load data. This process will take several minutes "
			"to several hours to complete depending on the options chosen." );
		return;
	}

	if( field( c_embedded ).toBool() ){
		setTitle( "Finished" );
		m_lbl->setText( "Click 'Finish' to create database. This process will take several minutes "
			"to several hours to complete depending on the options chosen." );
		return;
	}

	Bio::SqlServerSettings	settings;

	int	idx = field( c_serverType ).toInt();

	if( idx == 0 )
		settings.setServerType( Bio::SqlServerSettings::PostgreSQL );
	else
		settings.setServerType( Bio::SqlServerSettings::MySQL );

	settings.setHostName( field( c_hostName ).toString() );
	settings.setPort( field( c_portNumber ).toInt() );
	settings.setUserName( field( c_userName ).toString() );
	settings.setPassword( field( c_password ).toString() );
	settings.setDatabaseName( field( c_dbName ).toString() );

	Bio::SqlServer	server;

	if( server.connect( settings ) ){
		setTitle( "Finished" );
		if( field( c_createDB ).toBool() )
			m_lbl->setText( "Database connection successful, click 'Finish' to create database. This process will "
				"take several minutes to several hours to complete depending on the options chosen." );
		else
			m_lbl->setText( "Database connection successful, click 'Finish' to start using Snapshot." );
	}
	else {
		setTitle( "Database Connection Error" );
		m_lbl->setText( "Failed to connect to database. Please go back and check that the connection "
			"settings are correct.\n\n" + server.getLastError() );
	}
}
